// Per-release page. `getStaticPaths` enumerates every release slug so // `voltro build` pre-renders one HTML file per release. The loader runs at // build time (Node) where `highlightRelease` shiki-highlights the code // fences; in the browser it's a no-op and the plain marked HTML is used. import type { ReactNode } from 'react' import { useLoaderData, notFound, type LoaderFn } from '@voltro/web' import { highlightRelease } from '@voltro/changelog' import { T, useLocale } from '@voltro/i18n' import { releases, releaseBySlug, type Release } from '../../lib/releases' import { withLocalePrefix } from '../../lib/locale' export const renderMode = 'static' as const export const interactive = 'none' as const export const getStaticPaths = async (): Promise> => releases.map((release) => ({ params: { slug: release.slug } })) export const loader: LoaderFn<{ release: Release }> = async ({ params }) => { const release = params.slug ? releaseBySlug(params.slug) : undefined if (!release) return notFound(`release ${params.slug ?? ''}`) return { release: await highlightRelease(release) } } export const meta = ({ loaderData }: { loaderData: { release: Release } }) => ({ title: `${loaderData.release.title} — Changelog`, description: loaderData.release.summary, }) export default function ReleasePage(): ReactNode { const { release } = useLoaderData<{ release: Release }>() // The active locale (from the layout's URL provider) keeps the back-link on // the current language. const locale = useLocale() return (

{release.title}

· v{release.version} {release.tags.map((tag) => ( {tag} ))}

) }